package io.leo.leoui.viewgroups;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * 侧滑控件
 *
 * 就是在右侧添加一个或多个View，然后让它们在屏幕外面，滑动的时候出来。可以实现QQ侧滑删除功能
 */
public class SlideLayout extends ViewGroup {
    private Context context;
    private float lastX=0;
    private static final int TOUCH_MOVE_LEFT=0,TOUCH_MOVE_RIGHT=1,TOUCH_RELEASE=2,TOUCH_DOWN=3,TOUCH_SIDE=4;
    private static final int RIGHT_BUTTON_SHOW=0,RIGHT_BUTTON_HIDE=1;
    private int lastTouchState = TOUCH_RELEASE;
    private int rightButtonState=RIGHT_BUTTON_HIDE;

    private int rightButtonWidth = 0;

    private Scroller slideScroller;
    private SlideStateChangedListener listener;

    public SlideLayout(Context context) {
        this(context,null);
    }

    public SlideLayout(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SlideLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    /*******从此处开始是暴露给用户的Public方法********/
    /**
     * 设置SlideLayout的状态监听器
     * @param listener 监听器
     */
    public void setSlideStateChangedListener(SlideStateChangedListener listener){
        this.listener = listener;
    }

    /**
     * 打开SlideBar
     */
    public void openSlideBar(){
        if (rightButtonState==RIGHT_BUTTON_HIDE) {
            rightButtonState=RIGHT_BUTTON_SHOW;
            if (listener!=null) {
                listener.onSlideBarOpen();
            }
        }
        openScrollTranslate();
    }

    /**
     * 关闭SlideBar
     */
    public void closeSlideBar(){
        if (rightButtonState==RIGHT_BUTTON_SHOW){
            rightButtonState=RIGHT_BUTTON_HIDE;
            if (listener!=null) {
                listener.onSlideBarClosed();
            }
        }
        closeScrollTranslate();
    }

    /*******从此处以上是暴露给用户的Public方法********/


    private void init(Context context) {
        this.context = context;
        slideScroller = new Scroller(context);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (getChildCount()!=0){
            int selfWidthSize = MeasureSpec.getSize(widthMeasureSpec);
            int selfWidthMode = MeasureSpec.getMode(widthMeasureSpec);
            int selfHeightSize = MeasureSpec.getSize(heightMeasureSpec);
            int selfHeightMode = MeasureSpec.getMode(heightMeasureSpec);

            //总宽度
            int width = selfWidthSize;
            //内容部分的高度
            int contentHeightSpec;
            //SlideLayout认为第一个子View是显示在外部的Content，而之后的都是需要侧滑出来的SlideBar
            //SlideLayout规定无论content设置的是match_parent还是其他的，都会铺满整个SlideLayout，以用于将另外的按钮顶出layout，而高度就根据自己的来设置
            //SlideLayout的高度设置规则是其他子View的高度等于content的高度
            View content = getChildAt(0);
            switch (content.getLayoutParams().height){
                case LayoutParams.MATCH_PARENT:
                    contentHeightSpec = MeasureSpec.makeMeasureSpec(selfHeightSize,MeasureSpec.EXACTLY);
                    break;
                case LayoutParams.WRAP_CONTENT:
                    contentHeightSpec = MeasureSpec.makeMeasureSpec(selfHeightSize,MeasureSpec.AT_MOST);
                    break;
                default:
                    contentHeightSpec = MeasureSpec.makeMeasureSpec(content.getLayoutParams().height,MeasureSpec.EXACTLY);
                    break;
            }
            content.measure(MeasureSpec.makeMeasureSpec(selfWidthSize,MeasureSpec.EXACTLY),contentHeightSpec);


            for (int i=1;i<getChildCount();i++){
                View v = getChildAt(i);
                int viewWidthSpec = 0;
                //对于高度，我们设置为与content的高度相等
                int viewHeightSpec = MeasureSpec.makeMeasureSpec(content.getMeasuredHeight(),MeasureSpec.EXACTLY);
                //对于屏幕外面的SlideBar，要求必须指明一个宽度，否则设置宽度为0
                if (v.getLayoutParams().width!=LayoutParams.MATCH_PARENT&&v.getLayoutParams().width!=LayoutParams.WRAP_CONTENT){
                    viewWidthSpec = MeasureSpec.makeMeasureSpec(v.getLayoutParams().width,MeasureSpec.EXACTLY);
                }else{
                    viewHeightSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.EXACTLY);
                }
                v.measure(viewWidthSpec,viewHeightSpec);
                width+=MeasureSpec.getSize(viewWidthSpec);
            }

            setMeasuredDimension(MeasureSpec.makeMeasureSpec(width,MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(content.getMeasuredHeight(),MeasureSpec.EXACTLY));
        }
    }




    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        rightButtonWidth=0;
        int lastL=0;
        for (int i=0;i<getChildCount();i++){
            View v = getChildAt(i);
            v.layout(lastL,0,lastL=lastL+v.getMeasuredWidth(),getMeasuredHeight());
            if (i>0)
                rightButtonWidth+=v.getMeasuredWidth();
        }
    }



    @Override
    public void computeScroll() {
        if (slideScroller.computeScrollOffset()){
            scrollTo(slideScroller.getCurrX(), slideScroller.getCurrY());
            invalidate();
        }
    }

    private void openScrollTranslate(){
        slideScroller.startScroll(getScrollX(), 0,rightButtonWidth-getScrollX(), 0);
        invalidate();
    }

    private void closeScrollTranslate(){
        slideScroller.startScroll(getScrollX(), 0,0-getScrollX(), 0);
        invalidate();
    }

    @Override
    public void onViewAdded(View child) {
        super.onViewAdded(child);
    }

    @SuppressLint("LongLogTag")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction()==MotionEvent.ACTION_DOWN&&lastTouchState==TOUCH_RELEASE){
            lastX=event.getRawX();
            lastTouchState=TOUCH_DOWN;
        }else if (event.getAction()==MotionEvent.ACTION_MOVE){
            if (getScrollX()>=0&&getScrollX()<=rightButtonWidth){
                if (lastTouchState==TOUCH_DOWN){
                    lastTouchState = event.getRawX()-lastX>0?TOUCH_MOVE_RIGHT:TOUCH_MOVE_LEFT;
                }else if(lastTouchState==TOUCH_MOVE_RIGHT){
                    if (event.getRawX()>lastX)
                        scrollBy(-(int) (event.getRawX() - lastX), 0);
                    else
                        lastTouchState=TOUCH_MOVE_LEFT;
                    requestDisallowInterceptTouchEvent(true);
                }else if (lastTouchState==TOUCH_MOVE_LEFT){
                    if (event.getRawX()<lastX)
                        scrollBy((int) (lastX-event.getRawX()), 0);
                    else
                        lastTouchState=TOUCH_MOVE_RIGHT;
                    requestDisallowInterceptTouchEvent(true);
                }
            }else if (getScrollX()<0||getScrollX()>rightButtonWidth){
                lastTouchState=TOUCH_SIDE;
            }
            lastX=event.getRawX();
        }else if (event.getAction()==MotionEvent.ACTION_UP||event.getAction()==MotionEvent.ACTION_CANCEL){
            if (rightButtonState==RIGHT_BUTTON_HIDE){
                if (getScrollX()>=rightButtonWidth/3)
                    openSlideBar();
                else
                    closeSlideBar();
            }else if (rightButtonState==RIGHT_BUTTON_SHOW)
                if (getScrollX()>=rightButtonState/1.5)
                    closeSlideBar();
                else
                    openSlideBar();
            lastTouchState = TOUCH_RELEASE;
            lastX=0;
        }

        return true;
    }


    private float $;
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction()==MotionEvent.ACTION_DOWN){
            onTouchEvent(ev);
            $ = ev.getRawX();
        }else if (ev.getAction()==MotionEvent.ACTION_MOVE){
            onTouchEvent(ev);
            Log.i("MOVE", String.valueOf(ev.getRawX()-$));
            if (Math.abs(ev.getRawX()-$)>20)return true;
        }
        return false;
    }
}
